/*=+--+=#=+--     Unmanned Aerial System Management Software      --+=#=+--+=#*\
|          Copyright (C) 2011 Regents of the University of Colorado.           |
|                             All Rights Reserved.                             |

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

            Jack Elston                       Cory Dixon                        
|           elstonj@colorado.edu              dixonc@colorado.edu              |
|                                                                              |
\*=+--+=#=+--                 --+=#=+--+=#=+--                    --+=#=+--+=#*/

#ifndef __LEVEL2_LAYER_MANAGER_H
#define __LEVEL2_LAYER_MANAGER_H

#include <stdio.h>
#include <iostream>
#include <iomanip>
#include <string>

#include "LayerManager.h"

#define LEVEL2_STATION_FILE 

/*<-------Defines--------->*/
/*<------End Defines------>*/

//------- Structs ---------//
typedef struct _Level2ImgAlloc_t {
	String         file;
	double         x_off;    // x offset of img relative to geoImg[0]
	double         y_off;    // y offset of img relative to geoImg[0]
	double         scale_x;  // scale from this geo img to the one at geoImg[0]
	double         scale_y;  // scale from this geo img to the one at geoImg[0]

	double         tod;      // time of day of image

	GeoRefMap     *geoImg;   // geo referenced image

	_Level2ImgAlloc_t() {
		geoImg = NULL;
	}
	~_Level2ImgAlloc_t() {
		if( geoImg ) delete geoImg;
		geoImg = NULL;
	}
} Level2ImgAlloc_t;

typedef struct _L2NexradStations_t
{
	std::string icao;
	std::string name;
	std::string st;
	std::string county;

	double lat;
	double lon;
	int elev;
	int time;

	bool subscribed; // if subscribed
	bool time_loop; // if get time loop or just snap shot

	unsigned int currInd;

	GooCanvasItem *img_layer;
	GooCanvasItem *img_item_h;
	GooCanvasItem *img_item;
	GList         *img_alloc_list;

	GdkPixbuf     *loaded_pix;
	time_t         currImgTod;

	GooCanvasItem *station_item;
	GooCanvasItem *range_item;
	GooCanvasItem *text_item;

	_L2NexradStations_t() {
		subscribed     = false;
		time_loop      = false;
		station_item   = NULL;
		range_item     = NULL;
		text_item      = NULL;
		img_layer      = NULL;
		img_item       = NULL;
		img_item_h     = NULL;
		loaded_pix     = NULL;
		img_alloc_list = NULL;
		currImgTod     = 0;
	}

	~_L2NexradStations_t() {
		subscribed = false;
		time_loop  = false;

		if( img_item_h ) goo_canvas_item_remove( img_item_h );
		img_item   = NULL;
		img_item_h = NULL;

		for(unsigned int f_ind=0; f_ind < g_list_length(img_alloc_list); f_ind++) {
			// get the file
			Level2ImgAlloc_t *alloc = (Level2ImgAlloc_t *)g_list_nth_data(img_alloc_list,f_ind);
			if( alloc ) delete alloc;
		}

		if( img_alloc_list ) g_list_free( img_alloc_list );
		img_alloc_list = NULL;
	}
	bool getLooped() {
		return (time_loop);
	}	
	void setLooped(bool set) {
		time_loop = set;
	}	
	bool getSubscribed() {
		return subscribed;
	}	
	void setSubscribed(bool set) {
		subscribed = set;
	}
} L2NexradStations_t;

class Level2Manager : public LayerManager
{

	private:
		bool   playing;
		double timeScale;

		time_t time_offset;
		time_t min_time;
		time_t last_time;

		GList         *radar_list;
		GooCanvasItem *site_group;
		GooCanvasItem *site_group_h;
		GooCanvasItem *img_group;
		GtkWidget     *radar_window;

		GooCanvasItem *scale_item;
		GooCanvasItem *scale_item_h;
		void setup_scale(time_t startT, time_t currT, time_t stopT);

		L2NexradStations_t * findStation( GooCanvasItem *item );
		L2NexradStations_t * active_station;

		// -- http interface to radar maps
		static gboolean update_web_timeout(gpointer data);
		static gboolean update_image_timeout(gpointer data);
		static gboolean update_files_timeout(gpointer data);

		void one_time_init();
		void update_files();
		void update_images();
		void create_images(const char * dir, const char * file, string icao);

		GList         *radar_subs;

		GooCanvasItem *radar_layer;
		GHashTable    *tile_queue;

		void set_check_butons();
		void subscribeToRadar( bool timeLoop );

		// contains flags indicating the various special characters
		// the uri string contains, that will be replaced when calculating
		// the uri to download.
		uint32_t inspect_map_uri(const gchar *uri);
		gchar   *replace_uri(const gchar *uri, const gchar *site);

		Level2ImgAlloc_t * addImage(string file, string gfw);

		String siteFile;

	public:
		Level2Manager();
		~Level2Manager();

		// layer interface
		virtual void init(GPSMap *map = NULL);
		virtual void updateMap();
		virtual void translate_from_zoomChange(double zoom_factor);
		virtual bool setShown(int setTo = -1);

		void update_display_time(int dir = 1, bool userStep = false);

		// canas setup
		void create_canvas();
		void setup_item(GooCanvasItem *item);

		// signals
		static bool item_key_event_cb(GooCanvasItem *item, GooCanvasItem *target_item, GdkEventKey *event, Level2Manager *me);
		static bool item_button_press_event_cb(GooCanvasItem *item, GooCanvasItem *target_item, GdkEventButton *event, Level2Manager *me);
		static bool item_button_release_event_cb(GooCanvasItem *item, GooCanvasItem *target_item, GdkEventButton *event, Level2Manager *me);
		static bool item_motion_notify_event_cb(GooCanvasItem *item, GooCanvasItem *target_item, GdkEventMotion *event, Level2Manager *me);
		static bool on_focus_in(GooCanvasItem *item, GooCanvasItem *target, GdkEventFocus *event, gpointer data);
		static bool on_focus_out(GooCanvasItem *item, GooCanvasItem *target, GdkEventFocus *event, gpointer data);

		// media signals
		static bool Level2_media_button_cb(GooCanvasItem *item, GooCanvasItem *target_item, GdkEventButton *event, Level2Manager *me);

		// Level2 control window
		void create_radar_window();
		static void radar_button_clicked (GtkWidget *w, gpointer user_data);
		static void radar_cancel_clicked(GtkWidget *w, gpointer user_data);
		static gboolean radar_window_destroy(GtkWidget * widget, GdkEventKey * event, gpointer user_data);

		bool is_running() { return playing; }
		void step(int dir=1) {
			if( !playing ) update_display_time(dir,true);
		}
		void step_runRate(int dir=1) {
			if( dir > 0) timeScale *= 2.0;
			else if( dir < 0) timeScale /= 2.0;
		}	
		void toggle_running(int val=-1) {
			if( val < 0 ) playing ^= 1;
			else playing = val;
		}
};

#endif
